<script lang="ts" setup>
import { ref, unref, shallowRef, useAttrs, computed } from 'vue'
import type { TableProps } from 'ant-design-vue'
import { CheckCircleTwoTone, CloseCircleTwoTone } from '@ant-design/icons-vue'
import { isEmpty, isObjectAttribute } from '@/utils/is'
import { useI18n } from 'vue-i18n'
import { useColumnOptions } from './hooks/useColumnOptions'
import { BasicTableColumn } from './typing'

const { t } = useI18n()
const props = defineProps({
  selectChecked: { type: Boolean, default: false },
  showZebraStripes: { type: Boolean, default: true },
  sortByTotal: { type: Boolean, default: true }
})

const emit = defineEmits([
  'change',
  'check',
  'expand',
  'expandedRowsChange',
  'resizeColumn'
])

const attrs: TableProps = useAttrs()
const defaultAttrs = {
  bordered: true,
  scroll: { x: 1000 },
  rowClassName: (_record: Recordable, index: number) =>
    props.showZebraStripes && index % 2 === 1 ? 'system-table-striped' : null
}
const defaultOptions = useColumnOptions()

type Key = string | number
const selectedRowKeys = ref<Key[]>([])
const selectedRows = ref<Recordable[]>([])

const onSelectChange = function <T = any>(keys: Key[], rows: T[]) {
  selectedRowKeys.value = keys
  selectedRows.value = rows
}

const rowSelection = computed(() => {
  if (props.selectChecked) {
    return {
      selectedRowKeys: unref(selectedRowKeys),
      onChange: onSelectChange
    }
  }
  clearTableSelection()
  return null
})

const getBindValue = computed(() => ({
  ...defaultAttrs,
  ...attrs,
  rowSelection: unref(rowSelection)
}))
// console.log('BasicTable - attrs:', attrs)
// console.log('BasicTable - getBindValue: ', getBindValue)

const getTableSelection = () => ({
  selectedRowKeys: unref(selectedRowKeys),
  selectedRows: unref(selectedRows)
})

const clearTableSelection = () => {
  selectedRowKeys.value = []
  selectedRows.value = []
}

const getIndexNumber = (index: number) => {
  if (props.sortByTotal)
    return (
      (getBindValue.value.pagination.current - 1) *
        getBindValue.value.pagination.pageSize +
      index +
      1
    )
  return index + 1
}

const getColumnOptions = (column: BasicTableColumn<Recordable>): Indexable => ({
  ...defaultOptions[column.type + 'Options'],
  ...column[column.type + 'Options']
})

const getDisplayValue = (
  column: BasicTableColumn<Recordable>,
  data: Recordable
): String => {
  if (column.customRender) return column.customRender({ record: data })
  let options = column[column.type + 'Options']
  if (options) {
    if (options.fieldName) return data[options.fieldName]
    if (options.displayName) return options.displayName
  }
  if (column.isCheck) return t('system.check')
  if (data && data[column.dataIndex]) return data[column.dataIndex]
  return String(data)
}

const getDisplayColor = (
  column: BasicTableColumn<Recordable>
): string | Indexable => {
  let options = getColumnOptions(column)
  return options.color
}

const onCheck = async (
  column: BasicTableColumn<Recordable>,
  data: Recordable
) => {
  if (!column.isCheck) return
  const comp = shallowRef()
  let title = ''
  let options = getColumnOptions(column)
  if (options.fieldName) title = data[options.fieldName]
  else if (options.displayName) title = options.displayName
  else title = column.title
  const res = await column.component()
  comp.value = res.default
  emit('check', { component: comp.value, title, data })
}

const onChange = (
  pagination: Recordable,
  filters: Recordable,
  sorter: Recordable,
  { currentDataSource }: Recordable
) => {
  emit('change', pagination, filters, sorter, { currentDataSource })
}

const onExpand = (expanded: Recordable, record: Recordable) => {
  emit('expand', expanded, record)
}

const onExpandedRowsChange = (expandedRows: Recordable) => {
  emit('expandedRowsChange', expandedRows)
}

const onResizeColumn = (width: Recordable, column: Recordable) => {
  emit('resizeColumn', width, column)
}

defineExpose({ getTableSelection, clearTableSelection })
</script>

<template>
  <a-table
    v-bind="getBindValue"
    @change="onChange"
    @expand="onExpand"
    @expanded-rows-change="onExpandedRowsChange"
    @resize-column="onResizeColumn"
  >
    <template #bodyCell="{ column, record, index }">
      <!-- Action column display content -->
      <template v-if="column.dataIndex === 'index'">
        {{ getIndexNumber(index) }}
      </template>

      <!-- Action column display content -->
      <template v-else-if="column.dataIndex === 'actions'">
        <slot v-if="$slots.operate" name="operate" v-bind="record"></slot>
      </template>

      <!-- Empty data shows "-" -->
      <template
        v-else-if="
          isEmpty(record[column.dataIndex]) &&
          !isObjectAttribute(column, 'customRender')
        "
      >
        <a-typography-text type="secondary">-</a-typography-text>
      </template>

      <!-- Special display data handling, i.e. data containing the "type" attribute. -->
      <template v-else-if="column.type">
        <template v-if="column.type === 'text'">
          <span
            v-bind="getColumnOptions(column)"
            :class="{ isCheck: column.isCheck }"
            :style="`color: ${getDisplayColor(column)}`"
            @click="onCheck(column, record)"
          >
            {{ getDisplayValue(column, record) }}
          </span>
        </template>
        <template v-if="column.type === 'multiline'">
          <!-- <div
            v-bind="getColumnOptions(column)"
            :class="{ isCheck: column.isCheck }"
            :style="`color: ${getDisplayColor(column)}`"
            @click="onCheck(column, record)"
          > -->
          <pre style="margin-bottom: 0; overflow: visible">{{
            getDisplayValue(column, record)
          }}</pre>
          <!-- <p
              v-for="(item, idx) in getDisplayValue(column, record).split('\n')"
              :key="idx"
              style="margin-bottom: 0"
            >
              {{ item }}
            </p> -->
          <!-- </div> -->
        </template>
        <template v-if="column.type === 'password'">
          <span
            v-bind="getColumnOptions(column)"
            :class="{ isCheck: column.isCheck }"
            :style="`color: ${getDisplayColor(column)}`"
            @click="onCheck(column, record)"
          >
            {{ getDisplayValue(column, record).replaceAll(/./g, '*') }}
          </span>
        </template>
        <template v-if="column.type === 'switch'">
          <a-switch
            v-bind="getColumnOptions(column)"
            :class="{ isCheck: column.isCheck }"
            :checked="getDisplayValue(column, record)"
            :style="`color: ${getDisplayColor(column)}`"
            @click="onCheck(column, record)"
          />
        </template>

        <template v-if="column.type === 'rate'">
          <a-rate
            v-bind="getColumnOptions(column)"
            :value="getDisplayValue(column, record)"
            :class="{ isCheck: column.isCheck }"
            :style="`color: ${getDisplayColor(column)}`"
            disabled
            @click="onCheck(column, record)"
          />
        </template>

        <template v-if="column.type === 'slider'">
          <a-slider
            v-bind="getColumnOptions(column)"
            :class="{ isCheck: column.isCheck }"
            :value="getDisplayValue(column, record)"
            :style="`color: ${getDisplayColor(column)}`"
            @click="onCheck(column, record)"
          />
        </template>

        <template v-if="column.type === 'percentage'">
          <a-progress
            v-bind="getColumnOptions(column)"
            :class="{ isCheck: column.isCheck }"
            :percent="getDisplayValue(column, record)"
            :style="`color: ${getDisplayColor(column)}`"
            size="small"
            @click="onCheck(column, record)"
          />
        </template>

        <template v-if="column.type === 'link'">
          <a
            v-bind="getColumnOptions(column)"
            target="_blank"
            :class="{ isCheck: column.isCheck }"
            :href="getDisplayValue(column, record)"
            :style="`color: ${getDisplayColor(
              column
            )};text-decoration:underline;`"
            @click="onCheck(column, record)"
            >{{ getDisplayValue(column, record) }}</a
          >
        </template>

        <template v-if="column.type === 'boolIcon'">
          <component
            v-bind="getColumnOptions(column)"
            :class="{ isCheck: column.isCheck }"
            :is="
              getDisplayValue(column, record)
                ? CheckCircleTwoTone
                : CloseCircleTwoTone
            "
            :two-tone-color="
              getDisplayValue(column, record)
                ? getDisplayColor(column).success
                : getDisplayColor(column).danger
            "
            :style="{ fontSize: '16px', cursor: 'auto' }"
            @click="onCheck(column, record)"
          />
        </template>

        <template v-if="column.type === 'bools'">
          <component
            v-for="(item, idx) in record[column.dataIndex]"
            :key="idx"
            v-bind="getColumnOptions(column)"
            :class="{ isCheck: column.isCheck }"
            :is="item ? CheckCircleTwoTone : CloseCircleTwoTone"
            :two-tone-color="
              item
                ? getDisplayColor(column).success
                : getDisplayColor(column).danger
            "
            :style="{
              fontSize: '16px',
              cursor: 'auto',
              marginRight:
                idx !== record[column.dataIndex].length - 1 ? '8px' : ''
            }"
            @click="onCheck(column, item)"
          />
        </template>

        <template v-if="column.type === 'checkbox'">
          <a-checkbox
            v-bind="getColumnOptions(column)"
            :class="{ isCheck: column.isCheck }"
            :style="`color: ${getDisplayColor(column)}`"
            :checked="getDisplayValue(column, record)"
            @click="onCheck(column, record)"
          />
        </template>

        <template v-if="column.type === 'image'">
          <img
            v-bind="getColumnOptions(column)"
            :class="{ isCheck: column.isCheck }"
            :color="getDisplayColor(column)"
            :src="getDisplayValue(column, record)"
            @click="onCheck(column, record[column.dataIndex])"
          />
        </template>

        <template v-if="column.type === 'images'">
          <img
            v-for="(item, idx) in record[column.dataIndex]"
            v-bind="getColumnOptions(column)"
            :key="idx"
            :src="getDisplayValue(column, item)"
            :style="{
              marginRight:
                idx !== record[column.dataIndex].length - 1 ? '20px' : ''
            }"
            @click="onCheck(column, item)"
          />
        </template>

        <template v-if="column.type === 'tag'">
          <a-tag
            v-bind="getColumnOptions(column)"
            :class="{ isCheck: column.isCheck }"
            @click="onCheck(column, record[column.dataIndex])"
          >
            {{ getDisplayValue(column, record) }}
          </a-tag>
        </template>

        <template v-if="column.type === 'tags'">
          <a-tag
            v-for="(item, idx) in record[column.dataIndex]"
            :key="idx"
            v-bind="getColumnOptions(column)"
            :class="{ isCheck: column.isCheck }"
            @click="onCheck(column, item)"
          >
            {{ getDisplayValue(column, item) }}
          </a-tag>
        </template>

        <template v-if="column.type === 'check'">
          <a
            v-bind="getColumnOptions(column)"
            :class="{ isCheck: column.isCheck }"
            :style="`color: ${getDisplayColor(column)}`"
            @click="onCheck(column, record[column.dataIndex])"
          >
            {{ getDisplayValue(column, record) }}
          </a>
        </template>

        <template v-if="column.type === 'checks'">
          <a
            v-for="(item, idx) in record[column.dataIndex]"
            v-bind="getColumnOptions(column)"
            :class="{ isCheck: column.isCheck }"
            :key="idx"
            :style="`color: ${getDisplayColor(column)}`"
            @click="onCheck(column, item)"
          >
            {{ getDisplayValue(column, item) }}
            <a-divider
              type="vertical"
              v-if="idx !== record[column.dataIndex].length - 1"
            />
          </a>
        </template>
      </template>
    </template>
  </a-table>
</template>

<style lang="less" scoped>
.isCheck {
  cursor: pointer;
  text-decoration: underline;
}
</style>